//
// Copyright (c) 2007 Tridium, Inc.
// Licensed under the Academic Free License version 3.0
//
// History:
//   5 Mar 07  Brian Frank  Creation
//

package sedonac.namespace;

import sedona.Facets;

/**
 * Type is the interface for classes used to represent Sedona types
 * at compile time such as IrType or TypeDef.
 *
 * Not to be confused with sedona.Type used to represent types
 * in Java at runtime.
 */
public interface Type
{

//////////////////////////////////////////////////////////////////////////
// Identity
//////////////////////////////////////////////////////////////////////////

  /**
   * Get parent kit or throw UnsupportedException.
   */
  public Kit kit();

  /**
   * Get name in kit or throw UnsupportedException.
   */
  public String name();

  /**
   * Get name in kit or throw UnsupportedException.
   */
  public String qname();

  /**
   * Get facets metadata.
   */
  public Facets facets();

  /**
   * Is this type a primitive such as bool or int.
   */
  public boolean isPrimitive();

  /**
   * Is this reference type (anything not a primitive passed by pointer).
   */
  public boolean isRef();

  /**
   * Reference types, bool, float, and double can all be assigned null.
   */
  public boolean isNullable();

  /**
   * Get the base type or null.
   */
  public Type base();

  /**
   * Is this an array type.
   */
  public boolean isArray();

  /**
   * If array return item type.
   */
  public Type arrayOf();

  /**
   * Return array length or null if unbounded.
   */
  public ArrayType.Len arrayLength();

  /**
   * Is this type an instance of x (routed this method to TypeUtil.is)
   */
  public boolean is(Type x);

  /**
   * Return if o is the same type as this (signatures match).
   */
  public boolean equals(Object o);

  /**
   * Get the type signature which is either the primitive keyword,
   * a fully qualified type name such as sys::Component, or an array
   * type such as int[] or sys::Component[].
   */
  public String signature();

  /**
   * ToString must return signature().
   */
  public String toString();

  /**
   * Return the number of bytes this type occupies in memory.
   */
  public int sizeof();

  public boolean isObj();
  public boolean isComponent();
  public boolean isaComponent();
  public boolean isVirtual();
  public boolean isaVirtual();
  public boolean isBuf();
  public boolean isLog();
  public boolean isStr();
  public boolean isType();

  public boolean isBool();
  public boolean isByte();
  public boolean isFloat();
  public boolean isInt();
  public boolean isLong();
  public boolean isDouble();
  public boolean isShort();
  public boolean isVoid();
  public boolean isInteger(); // byte, short, int
  public boolean isNumeric(); // integer, float, long, double
  public boolean isWide();    // long/double 

  public abstract boolean isReflective();
  public abstract int id(); // if reflective

//////////////////////////////////////////////////////////////////////////
// Slots
//////////////////////////////////////////////////////////////////////////

  /**
   * Get the list of all slots, which included inherited slots
   * if the Inherit step has been run.
   */
  public Slot[] slots();

  /**
   * Get the list of all slots declared by me (slot.parent == this).
   * This list is slots() without all the inherited slots.
   */
  public Slot[] declared();

  /**
   * Get a slot by name or return null if no slot with specified name.
   * This includes inherited slots if Inherit step has been run.
   */
  public Slot slot(String name);

  /**
   * Add a slot to this type (typically during the Inherit step).
   */
  public void addSlot(Slot slot);

//////////////////////////////////////////////////////////////////////////
// Type Id
//////////////////////////////////////////////////////////////////////////

  // these type ids must match those generated by the compiler
  // and used by the vm to identify predefined types

  public static final int voidId   = sedona.Type.voidId;
  public static final int boolId   = sedona.Type.boolId;
  public static final int byteId   = sedona.Type.byteId;
  public static final int shortId  = sedona.Type.shortId;
  public static final int intId    = sedona.Type.intId;
  public static final int longId   = sedona.Type.longId;
  public static final int floatId  = sedona.Type.floatId;
  public static final int doubleId = sedona.Type.doubleId;
  public static final int bufId    = sedona.Type.bufId;
  
//////////////////////////////////////////////////////////////////////////
// Flags
//////////////////////////////////////////////////////////////////////////

  // these flags need to be kept in sync with sedona.Type so that the 
  // TypeManifest flags can be correctly written.
  
  public static final int ABSTRACT  = sedona.Type.ABSTRACT;
  public static final int CONST     = sedona.Type.CONST;
  public static final int FINAL     = sedona.Type.FINAL;
  public static final int INTERNAL  = sedona.Type.INTERNAL;
  public static final int PUBLIC    = sedona.Type.PUBLIC;

  public int flags();
  public boolean isAbstract();
  public boolean isConst();
  public boolean isFinal();
  public boolean isInternal();
  public boolean isPublic();

}
